package com.uzai.console.service.report.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.converters.longconverter.LongStringConverter;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.uzai.common.enums.DeviceTypeEnum;
import com.uzai.common.exception.BusinessException;
import com.uzai.common.result.ResponseCode;
import com.uzai.common.utils.Math;
import com.uzai.console.common.ResponseMsg;
import com.uzai.console.common.UzaiRespVo;
import com.uzai.console.common.utils.DateUtil;
import com.uzai.console.common.utils.Tools;
import com.uzai.console.common.utils.ZipUtils;
import com.uzai.console.config.UzaiConsoleSysConfig;
import com.uzai.console.constant.CacheKey;
import com.uzai.console.constant.Const;
import com.uzai.console.dto.feign.report.RobotDataReportFeignDto;
import com.uzai.console.dto.report.RobotDataReportExportResultDto;
import com.uzai.console.dto.report.RobotDataReportQuery;
import com.uzai.console.dto.report.RobotDataReportQuery;
import com.uzai.console.dto.stats.OrderProfitStatsDto;
import com.uzai.console.dto.stats.OrderProfitStatsQuery;
import com.uzai.console.dto.wechatprivate.devicewechatinfo.DeviceWechatInfoQuery;
import com.uzai.console.dto.wechatwork.devicewxworkinfo.DeviceWxworkInfoQuery;
import com.uzai.console.dto.wxpubmanage.WxpubInfoListQuery;
import com.uzai.console.entity.Device;
import com.uzai.console.entity.DeviceWechatInfo;
import com.uzai.console.entity.DeviceWxworkInfo;
import com.uzai.console.entity.Merchant;
import com.uzai.console.entity.wxpubmanage.WxpubInfoEntity;
import com.uzai.console.enums.ExportInfoTypeEnum;
import com.uzai.console.enums.SmsType;
import com.uzai.console.mapper.*;
import com.uzai.console.mapper.stats.OrderProfitStatsMapper;
import com.uzai.console.service.device.DeviceService;
import com.uzai.console.service.exportinfo.ExportInfoService;
import com.uzai.console.service.feign.UzaiReportServerFeignService;
import com.uzai.console.service.report.RobotDataReportService;
import com.uzai.console.service.stats.OrderProfitService;
import com.uzai.console.service.user.impl.WechatUserServiceImpl;
import com.uzai.console.vo.exportinfo.ExportAmountVo;
import com.uzai.console.vo.feign.report.RobotDataReportFeignVo;
import com.uzai.console.vo.report.RobotDataReportExport;
import com.uzai.console.vo.report.RobotDataReportVo;
import com.uzai.console.vo.report.OrderRevenueReportVo;
import com.uzai.console.vo.report.RobotDataReportVo;
import com.uzai.console.vo.stats.orderprofit.OrderProfitPageVo;
import com.uzai.console.vo.stats.orderprofit.OrderProfitStatsVo;
import com.uzai.console.vo.stats.orderprofit.OrderProfitVo;
import io.swagger.annotations.ApiModelProperty;
import org.apache.tools.zip.ZipOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.unit.DataUnit;

import javax.xml.crypto.Data;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit;

/**
 * 机器人数据报表
 * @author liuqi
 * @date 2021年08月25日 20:18
 */
@Service
public class RobotDataReportServiceImpl implements RobotDataReportService {

    private Logger logger = LoggerFactory.getLogger(RobotDataReportServiceImpl.class);

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private OrderProfitStatsMapper orderProfitStatsMapper;
    @Autowired
    private DeviceWechatInfoMapper deviceWechatInfoMapper;
    @Autowired
    private DeviceWxworkInfoMapper deviceWxworkInfoMapper;
    @Autowired
    private WxpubInfoMapper wxpubInfoMapper;
    @Autowired
    private UzaiReportServerFeignService uzaiReportServerFeignService;
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private SysConfigMapper sysConfigMapper;
    @Autowired
    private MerchantMapper merchantMapper;
    @Autowired
    private UzaiConsoleSysConfig uzaiConsoleSysConfig;
    @Autowired
    private ExportInfoService exportInfoService;

    /**
     * 机器人数据报表
     * @author liuqi
     * @date 2021/8/25 11:38
     * @param robotDataReportQuery
     * @return null
     */
    public Page<RobotDataReportVo> robotDataReport(RobotDataReportQuery robotDataReportQuery){

        //返回到页面分页对象
        Page<RobotDataReportVo> pageVo = new Page<>();
        robotDataReportQuery.convert(pageVo);
        //新建返回到页面的LIST对象
        List<RobotDataReportVo> robotDataReportVoList = new ArrayList<>();

        Long merId = robotDataReportQuery.getMerId();
        String deviceType = robotDataReportQuery.getDeviceType();
        //机器人查询条件
        List<Long> deviceUniqueIdList = robotDataReportQuery.getDeviceUniqueIdList();
        //查询开始时间
        Integer queryStartTime = robotDataReportQuery.getQueryStartTime();
        //查询结束时间
        Integer queryEndTime = robotDataReportQuery.getQueryEndTime();

        //判断查询条件
        if(merId == null){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "系统参数错误");
        }

        if(StringUtils.isBlank(deviceType)){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请选择设备类型");
        }

        if(queryStartTime == null){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入时间范围");
        }

        if(queryEndTime == null){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入时间范围");
        }

        int now = DateUtil.getNowTime();

        if(queryEndTime.intValue() < queryStartTime.intValue()){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "结束时间不能早于开始时间");
        }

        if(queryEndTime.intValue()- queryStartTime.intValue() > 31*24*3600){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "最多只能查询31天的报表");
        }

        if(now - queryStartTime.intValue() > 90*24*3600){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "最早只能查询90天以内的报表");
        }

        //手动处理机器人分页查询-如果是机器人昵称，则按照中文gbk排序
        List<OrderItem> orderItemList = robotDataReportQuery.getOrderItemList();
        if(orderItemList != null && orderItemList.size() > 0){
            for (OrderItem orderItem :orderItemList){
                if("device_name".equals(orderItem.getColumn())){
                    orderItem.setColumn(" convert( " + orderItem.getColumn() + " using gbk) ");
                }
            }
        }

        //个人微信
        if(DeviceTypeEnum.DT_PC_WECHAT.getKey().equals(deviceType)){
            Page<DeviceWechatInfo> page = new Page<>();
            robotDataReportQuery.convert(page);
            DeviceWechatInfoQuery deviceWechatInfoQuery = new DeviceWechatInfoQuery();
            BeanUtils.copyProperties(robotDataReportQuery, deviceWechatInfoQuery);
            deviceWechatInfoQuery.setIdList(robotDataReportQuery.getDeviceUniqueIdList());
            deviceWechatInfoQuery.setMerId(merId);
            ArrayList<DeviceWechatInfo> deviceWechatInfoList =  deviceWechatInfoMapper.findByList(page, deviceWechatInfoQuery);
            BeanUtils.copyProperties(page, pageVo);
            if(deviceWechatInfoList != null && deviceWechatInfoList.size() > 0){
                for (DeviceWechatInfo deviceWechatInfo : deviceWechatInfoList){


                    RobotDataReportVo robotDataReportVo = new RobotDataReportVo();
                    robotDataReportVo.setDeviceUniqueId(deviceWechatInfo.getId());
                    robotDataReportVo.setDeviceName(deviceWechatInfo.getDeviceName());
                    robotDataReportVo.setDeviceRemark(deviceWechatInfo.getDeviceRemark());
                    robotDataReportVo.setHeadImgUrl(deviceWechatInfo.getHeadImgUrl());
                    robotDataReportVoList.add(robotDataReportVo);
                }
            }
        }else if(DeviceTypeEnum.DT_WORK_WECHAT.getKey().equals(deviceType)){
            Page<DeviceWxworkInfo> page = new Page<>();
            robotDataReportQuery.convert(page);
            DeviceWxworkInfoQuery deviceWxworkInfoQuery = new DeviceWxworkInfoQuery();
            BeanUtils.copyProperties(robotDataReportQuery, deviceWxworkInfoQuery);
            deviceWxworkInfoQuery.setIdList(robotDataReportQuery.getDeviceUniqueIdList());
            deviceWxworkInfoQuery.setMerId(merId);
            ArrayList<DeviceWxworkInfo> deviceWxworkInfoList =  deviceWxworkInfoMapper.findByList(page, deviceWxworkInfoQuery);
            BeanUtils.copyProperties(page, pageVo);
            if(deviceWxworkInfoList != null && deviceWxworkInfoList.size() > 0){
                for (DeviceWxworkInfo deviceWxworkInfo : deviceWxworkInfoList){
                    RobotDataReportVo robotDataReportVo = new RobotDataReportVo();
                    robotDataReportVo.setDeviceUniqueId(deviceWxworkInfo.getId());
                    robotDataReportVo.setDeviceName(deviceWxworkInfo.getDeviceName());
                    robotDataReportVo.setDeviceRemark(deviceWxworkInfo.getDeviceRemark());
                    robotDataReportVo.setHeadImgUrl(deviceWxworkInfo.getHeadImgUrl());
                    robotDataReportVoList.add(robotDataReportVo);
                }
            }
        }else if(DeviceTypeEnum.WX_PUB.getKey().equals(deviceType)){
            Page<WxpubInfoEntity> page = new Page<>();
            robotDataReportQuery.convert(page);
            WxpubInfoListQuery wxpubInfoListQuery = new WxpubInfoListQuery();
            BeanUtils.copyProperties(robotDataReportQuery, wxpubInfoListQuery);
            wxpubInfoListQuery.setIdList(robotDataReportQuery.getDeviceUniqueIdList());
            wxpubInfoListQuery.setMerId(merId);
            List<WxpubInfoEntity> wxpubInfoEntityList =  wxpubInfoMapper.queryList(page, wxpubInfoListQuery);
            BeanUtils.copyProperties(page, pageVo);
            if(wxpubInfoEntityList != null && wxpubInfoEntityList.size() > 0){
                for (WxpubInfoEntity wxpubInfoEntity : wxpubInfoEntityList){
                    RobotDataReportVo robotDataReportVo = new RobotDataReportVo();
                    robotDataReportVo.setDeviceUniqueId(wxpubInfoEntity.getId());
                    robotDataReportVo.setDeviceName(wxpubInfoEntity.getDeviceName());
                    robotDataReportVo.setDeviceRemark(wxpubInfoEntity.getDeviceRemark());
                    robotDataReportVo.setHeadImgUrl(wxpubInfoEntity.getHeadImgUrl());
                    robotDataReportVoList.add(robotDataReportVo);
                }
            }
        }

        //有机器人才去查询
        if(robotDataReportVoList != null && robotDataReportVoList.size() > 0){

            //封装微服务机器人参数
            List<Long> robotIds = new ArrayList<>();
            for(RobotDataReportVo robotDataReportVo : robotDataReportVoList){
                //子账号负责的机器人列表
                List<Long> subDeviceUniqueIdList = robotDataReportQuery.getSubDeviceUniqueIdList();
                if(subDeviceUniqueIdList != null && subDeviceUniqueIdList.size() > 0){
                    for (Long subDeviceUniqueId : subDeviceUniqueIdList){
                        if(subDeviceUniqueId.longValue() == robotDataReportVo.getDeviceUniqueId().longValue()){
                            robotIds.add(robotDataReportVo.getDeviceUniqueId());
                        }
                    }
                }else{
                    robotIds.add(robotDataReportVo.getDeviceUniqueId());
                }
            }

            RobotDataReportFeignDto robotDataReportFeignDto = new RobotDataReportFeignDto();
            robotDataReportFeignDto.setStartTime(queryStartTime);
            robotDataReportFeignDto.setEndTime(queryEndTime);
            robotDataReportFeignDto.setRobotIds(robotIds);
            robotDataReportFeignDto.setMerId(merId);
            robotDataReportFeignDto.setDeviceType(DeviceTypeEnum.getByKey(deviceType).getId());
            UzaiRespVo<List<RobotDataReportFeignVo>> uzaiRespVo =  uzaiReportServerFeignService.robotDataReport(robotDataReportFeignDto);
            //logger.info("----调用机器人数据报表微服务---para={}, result={}", JSONObject.toJSONString(robotDataReportFeignDto), JSONObject.toJSONString(uzaiRespVo));
            if(uzaiRespVo != null && uzaiRespVo.getCode() == 200){
                List<RobotDataReportFeignVo> robotDataReportFeignVoList = uzaiRespVo.getData();
                if(robotDataReportFeignVoList != null && robotDataReportFeignVoList.size() > 0){
                    for (RobotDataReportFeignVo robotDataReportFeignVo : robotDataReportFeignVoList){
                        for (RobotDataReportVo robotDataReportVo : robotDataReportVoList){
                            //匹配查找返回列表中的对象
                            if(robotDataReportVo.getDeviceUniqueId().longValue() == robotDataReportFeignVo.getRobotId().longValue()){

                                //对象赋值
                                BeanUtils.copyProperties(robotDataReportFeignVo, robotDataReportVo);

                                //注册用户总量
                                Integer registerUserCount = Tools.getInteger(robotDataReportFeignVo.getRegisterUserCount());
                                //注册用户下单总量
                                Integer registerUserPlaceOrderCount = Tools.getInteger(robotDataReportFeignVo.getRegisterUserPlaceOrderCount());
                                if(registerUserCount.intValue() != 0){
                                    //注册用户下单率
                                    Double registerUserPlaceOrderRate = Math.mul(Math.div(Double.parseDouble(String.valueOf(registerUserPlaceOrderCount)), Double.parseDouble(String.valueOf(registerUserCount)), 4), 100);
                                    robotDataReportVo.setRegisterUserPlaceOrderRate(registerUserPlaceOrderRate);
                                }else{
                                    robotDataReportVo.setRegisterUserPlaceOrderRate(0.00d);
                                }

                                //直接添加会员总量
                                Integer directUserCount = Tools.getInteger(robotDataReportFeignVo.getDirectUserCount());
                                //直接添加会员的总下单量
                                Integer directUserPlaceOrderCount = Tools.getInteger(robotDataReportFeignVo.getDirectUserPlaceOrderCount());
                                if(directUserCount.intValue() != 0){
                                    //直接添加用户下单率
                                    Double registerUserPlaceOrderRate = Math.mul(Math.div(Double.parseDouble(String.valueOf(directUserPlaceOrderCount)), Double.parseDouble(String.valueOf(directUserCount)), 4), 100);
                                    robotDataReportVo.setDirectUserPlaceOrderRate(registerUserPlaceOrderRate);
                                }else{
                                    robotDataReportVo.setDirectUserPlaceOrderRate(0.00d);
                                }

                                //自然裂变会员总量
                                Integer fissionUserCount = Tools.getInteger(robotDataReportFeignVo.getFissionUserCount());
                                //自然裂变会员的总下单量
                                Integer fissionUserPlaceOrderCount = Tools.getInteger(robotDataReportFeignVo.getFissionUserPlaceOrderCount());
                                if(fissionUserCount.intValue() != 0){
                                    //自然裂变用户下单率
                                    Double fissionUserPlaceOrderRate = Math.mul(Math.div(Double.parseDouble(String.valueOf(fissionUserPlaceOrderCount)), Double.parseDouble(String.valueOf(fissionUserCount)), 4), 100);
                                    robotDataReportVo.setFissionUserPlaceOrderRate(fissionUserPlaceOrderRate);
                                }else{
                                    robotDataReportVo.setFissionUserPlaceOrderRate(0.00d);
                                }

                                //总订单量
                                Integer orderCount = Tools.getInteger(robotDataReportFeignVo.getTbTotalOrderCount())
                                        + Tools.getInteger(robotDataReportFeignVo.getJdTotalOrderCount())
                                        + Tools.getInteger(robotDataReportFeignVo.getPddTotalOrderCount())
                                        + Tools.getInteger(robotDataReportFeignVo.getVphTotalOrderCount())
                                        + Tools.getInteger(robotDataReportFeignVo.getElmTotalOrderCount())
                                        + Tools.getInteger(robotDataReportFeignVo.getMtTotalOrderCount())
                                        + Tools.getInteger(robotDataReportFeignVo.getKsTotalOrderCount())
                                        + Tools.getInteger(robotDataReportFeignVo.getDyTotalOrderCount());
                                robotDataReportVo.setOrderCount(orderCount);

                                //总预估买家分佣
                                Double totalCommissionCount_tb_jd = Math.add(Tools.getDouble(robotDataReportFeignVo.getTbTotalCommissionCount()), Tools.getDouble(robotDataReportFeignVo.getJdTotalCommissionCount()));
                                Double totalCommissionCount_tb_jd_pdd = Math.add(totalCommissionCount_tb_jd, Tools.getDouble(robotDataReportFeignVo.getPddTotalCommissionCount()));
                                Double totalCommissionCount_tb_jd_pdd_vph = Math.add(totalCommissionCount_tb_jd_pdd, Tools.getDouble(robotDataReportFeignVo.getVphTotalCommissionCount()));
                                Double totalCommissionCount_tb_jd_pdd_vph_elm = Math.add(totalCommissionCount_tb_jd_pdd_vph, Tools.getDouble(robotDataReportFeignVo.getElmTotalCommissionCount()));
                                Double totalCommissionCount_tb_jd_pdd_vph_elm_mt = Math.add(totalCommissionCount_tb_jd_pdd_vph_elm, Tools.getDouble(robotDataReportFeignVo.getMtTotalCommissionCount()));
                                Double totalCommissionCount_tb_jd_pdd_vph_elm_mt_dy = Math.add(totalCommissionCount_tb_jd_pdd_vph_elm_mt, Tools.getDouble(robotDataReportFeignVo.getDyTotalCommissionCount()));
                                Double totalCommissionCount_tb_jd_pdd_vph_elm_mt_dy_ks = Math.add(totalCommissionCount_tb_jd_pdd_vph_elm_mt_dy, Tools.getDouble(robotDataReportFeignVo.getKsTotalCommissionCount()));
                                robotDataReportVo.setTotalCommissionCount(totalCommissionCount_tb_jd_pdd_vph_elm_mt_dy_ks);

                                //总预估利润
                                Double totalProfitCount_tb_jd = Math.add(Tools.getDouble(robotDataReportFeignVo.getTbTotalProfitCount()), Tools.getDouble(robotDataReportFeignVo.getJdTotalProfitCount()));
                                Double totalProfitCount_tb_jd_pdd = Math.add(totalProfitCount_tb_jd, Tools.getDouble(robotDataReportFeignVo.getPddTotalProfitCount()));
                                Double totalProfitCount_tb_jd_pdd_vph = Math.add(totalProfitCount_tb_jd_pdd, Tools.getDouble(robotDataReportFeignVo.getVphTotalProfitCount()));
                                Double totalProfitCount_tb_jd_pdd_vph_elm = Math.add(totalProfitCount_tb_jd_pdd_vph, Tools.getDouble(robotDataReportFeignVo.getElmTotalProfitCount()));
                                Double totalProfitCount_tb_jd_pdd_vph_elm_mt = Math.add(totalProfitCount_tb_jd_pdd_vph_elm, Tools.getDouble(robotDataReportFeignVo.getMtTotalProfitCount()));
                                Double totalProfitCount_tb_jd_pdd_vph_elm_mt_dy = Math.add(totalProfitCount_tb_jd_pdd_vph_elm_mt, Tools.getDouble(robotDataReportFeignVo.getDyTotalProfitCount()));
                                Double totalProfitCount_tb_jd_pdd_vph_elm_mt_dy_ks = Math.add(totalProfitCount_tb_jd_pdd_vph_elm_mt_dy, Tools.getDouble(robotDataReportFeignVo.getKsTotalProfitCount()));
                                robotDataReportVo.setTotalProfitCount(totalProfitCount_tb_jd_pdd_vph_elm_mt_dy);
                                break;
                            }
                        }
                    }
                }
            }
        }

        pageVo.setRecords(robotDataReportVoList);
        //将分页信息复制到返回到页面的分页MO当中
        return pageVo;
    }

    /**
     * 机器人数据查询结果导出文件前检验接口
     * @author liuqi
     * @date 2021/8/25 11:38
     * @param robotDataReportQuery
     */
    public ExportAmountVo getExportAmount(RobotDataReportQuery robotDataReportQuery){

        //执行分页查询对象
        //返回到页面分页对象
        Page<RobotDataReportVo> pageVo = new Page<>();
        robotDataReportQuery.convert(pageVo);
        //新建返回到页面的LIST对象
        List<RobotDataReportVo> robotDataReportVoList = new ArrayList<>();

        Long merId = robotDataReportQuery.getMerId();
        String deviceType = robotDataReportQuery.getDeviceType();
        //机器人查询条件
        List<Long> deviceUniqueIdList = robotDataReportQuery.getDeviceUniqueIdList();
        //查询开始时间
        Integer queryStartTime = robotDataReportQuery.getQueryStartTime();
        //查询结束时间
        Integer queryEndTime = robotDataReportQuery.getQueryEndTime();

        //判断查询条件
        if(merId == null){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "系统参数错误");
        }

        if(StringUtils.isBlank(deviceType)){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请选择设备类型");
        }

        if(queryStartTime == null){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入时间范围");
        }

        if(queryEndTime == null){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入时间范围");
        }

        int now = DateUtil.getNowTime();

        if(queryEndTime.intValue() < queryStartTime.intValue()){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "结束时间不能早于开始时间");
        }

        if(queryEndTime.intValue()- queryStartTime.intValue() > 31*24*3600){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "最多只能查询31天的报表");
        }

        if(now - queryStartTime.intValue() > 90*24*3600){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "最早只能查询90天以内的报表");
        }

        //手动处理机器人分页查询-如果是机器人昵称，则按照中文gbk排序
        List<OrderItem> orderItemList = robotDataReportQuery.getOrderItemList();
        if(orderItemList != null && orderItemList.size() > 0){
            for (OrderItem orderItem :orderItemList){
                if("device_name".equals(orderItem.getColumn())){
                    orderItem.setColumn(" convert( " + orderItem.getColumn() + " using gbk) ");
                }
            }
        }

        //个人微信
        if(DeviceTypeEnum.DT_PC_WECHAT.getKey().equals(deviceType)){
            Page<DeviceWechatInfo> page = new Page<>();
            robotDataReportQuery.convert(page);
            DeviceWechatInfoQuery deviceWechatInfoQuery = new DeviceWechatInfoQuery();
            BeanUtils.copyProperties(robotDataReportQuery, deviceWechatInfoQuery);
            deviceWechatInfoQuery.setIdList(robotDataReportQuery.getDeviceUniqueIdList());
            deviceWechatInfoQuery.setMerId(merId);
            ArrayList<DeviceWechatInfo> deviceWechatInfoList =  deviceWechatInfoMapper.findByList(page, deviceWechatInfoQuery);
            BeanUtils.copyProperties(page, pageVo);
            if(deviceWechatInfoList != null && deviceWechatInfoList.size() > 0){
                for (DeviceWechatInfo deviceWechatInfo : deviceWechatInfoList){


                    RobotDataReportVo robotDataReportVo = new RobotDataReportVo();
                    robotDataReportVo.setDeviceUniqueId(deviceWechatInfo.getId());
                    robotDataReportVo.setDeviceName(deviceWechatInfo.getDeviceName());
                    robotDataReportVo.setDeviceRemark(deviceWechatInfo.getDeviceRemark());
                    robotDataReportVo.setHeadImgUrl(deviceWechatInfo.getHeadImgUrl());
                    robotDataReportVoList.add(robotDataReportVo);
                }
            }
        }else if(DeviceTypeEnum.DT_WORK_WECHAT.getKey().equals(deviceType)){
            Page<DeviceWxworkInfo> page = new Page<>();
            robotDataReportQuery.convert(page);
            DeviceWxworkInfoQuery deviceWxworkInfoQuery = new DeviceWxworkInfoQuery();
            BeanUtils.copyProperties(robotDataReportQuery, deviceWxworkInfoQuery);
            deviceWxworkInfoQuery.setIdList(robotDataReportQuery.getDeviceUniqueIdList());
            deviceWxworkInfoQuery.setMerId(merId);
            ArrayList<DeviceWxworkInfo> deviceWxworkInfoList =  deviceWxworkInfoMapper.findByList(page, deviceWxworkInfoQuery);
            BeanUtils.copyProperties(page, pageVo);
            if(deviceWxworkInfoList != null && deviceWxworkInfoList.size() > 0){
                for (DeviceWxworkInfo deviceWxworkInfo : deviceWxworkInfoList){
                    RobotDataReportVo robotDataReportVo = new RobotDataReportVo();
                    robotDataReportVo.setDeviceUniqueId(deviceWxworkInfo.getId());
                    robotDataReportVo.setDeviceName(deviceWxworkInfo.getDeviceName());
                    robotDataReportVo.setDeviceRemark(deviceWxworkInfo.getDeviceRemark());
                    robotDataReportVo.setHeadImgUrl(deviceWxworkInfo.getHeadImgUrl());
                    robotDataReportVoList.add(robotDataReportVo);
                }
            }
        }else if(DeviceTypeEnum.WX_PUB.getKey().equals(deviceType)){
            Page<WxpubInfoEntity> page = new Page<>();
            robotDataReportQuery.convert(page);
            WxpubInfoListQuery wxpubInfoListQuery = new WxpubInfoListQuery();
            BeanUtils.copyProperties(robotDataReportQuery, wxpubInfoListQuery);
            wxpubInfoListQuery.setIdList(robotDataReportQuery.getDeviceUniqueIdList());
            wxpubInfoListQuery.setMerId(merId);
            List<WxpubInfoEntity> wxpubInfoEntityList =  wxpubInfoMapper.queryList(page, wxpubInfoListQuery);
            BeanUtils.copyProperties(page, pageVo);
            if(wxpubInfoEntityList != null && wxpubInfoEntityList.size() > 0){
                for (WxpubInfoEntity wxpubInfoEntity : wxpubInfoEntityList){
                    RobotDataReportVo robotDataReportVo = new RobotDataReportVo();
                    robotDataReportVo.setDeviceUniqueId(wxpubInfoEntity.getId());
                    robotDataReportVo.setDeviceName(wxpubInfoEntity.getDeviceName());
                    robotDataReportVo.setDeviceRemark(wxpubInfoEntity.getDeviceRemark());
                    robotDataReportVo.setHeadImgUrl(wxpubInfoEntity.getHeadImgUrl());
                    robotDataReportVoList.add(robotDataReportVo);
                }
            }
        }


        //单个机器人查询总数
        long totalCount = pageVo.getTotal();
        if(totalCount == 0){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "查询结果记录数为0");
        }

        String price = sysConfigMapper.selectByKey("export_record_price");

        //计算本次导出费用
        double amountTotal = 0.00D;
        if(amountTotal <= 10000){ //少于1万条，只收取1元
            amountTotal = 1.00D;
        }else{//总导出数大于1万条，则根据单价来计算，超过1万条的按照100条的单价费用来计算
            amountTotal = com.uzai.common.utils.Math.add(1.0D, ((totalCount - 10000)/100 + 1) * Double.parseDouble(price));
        }
        ExportAmountVo  exportAmountVo = new ExportAmountVo();
        exportAmountVo.setAmountTotal(amountTotal);
        exportAmountVo.setCountTotal(totalCount);
        exportAmountVo.setPrice(Double.parseDouble(price));

        return exportAmountVo;
    }

    /**
     * 机器人数据统计结果导出数据
     * @author liuqi
     * @date 2021/8/13 11:38
     * @param robotDataReportExportResultDto
     * @return null
     */
    public void exportByQeuryResult(RobotDataReportExportResultDto robotDataReportExportResultDto){

        if(robotDataReportExportResultDto.getMerId() == null ){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.PARAM_ERROR);
        }

        if(org.apache.commons.lang3.StringUtils.isBlank(robotDataReportExportResultDto.getCode())){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入验证码");
        }

        Merchant merchant = merchantMapper.selectById(robotDataReportExportResultDto.getMerId());
        if(merchant == null ){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "运营商不存在");
        }

        //查询输入的验证码是否为系统默认密码
        if(!robotDataReportExportResultDto.getCode().equals(uzaiConsoleSysConfig.getDefaultPassword())){

            String val = (String) redisTemplate.opsForValue().get(String.format(CacheKey.ROBOT_DATA_REPORT_EXPORT, robotDataReportExportResultDto.getMerId()));
            if (org.apache.commons.lang3.StringUtils.isNotBlank(val)){
                throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "30分钟只允许导出一次");
            }

            //获取存在redis中的验证码
            String codeByRedis = (String) redisTemplate.opsForValue().get(String.format(SmsType.SPECIAL_OPERATE.getDesc(), merchant.getMobile()));
            //判断验证码是否过期
            if (org.apache.commons.lang3.StringUtils.isBlank(codeByRedis)){
                throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.CODE_MISS);
            }

            //验证码是否正确
            if (!codeByRedis.equals(robotDataReportExportResultDto.getCode())){
                throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.CODE_ERR);
            }

            //验证成功了删除验证码
            redisTemplate.delete(String.format(SmsType.SPECIAL_OPERATE.getDesc(), merchant.getMobile()));
        }

        //页面查询条件
        RobotDataReportQuery robotDataReportQuery = robotDataReportExportResultDto.getRobotDataReportQuery();
        robotDataReportQuery.setMerId(robotDataReportExportResultDto.getMerId());

        //计算费用
        ExportAmountVo exportAmountVo = getExportAmount(robotDataReportQuery);

        //生成ZIP文件流
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream out = new ZipOutputStream(outputStream);

        //每个excel表格订单最大数为10000条
        int exportExcelMaxNum = Const.ExprotFile.EXPORT_EXCEL_MAX_NUM;
        //导出excel文件序号
        int exportFileNumber = 0;

        //存放导出文件对象(一万条一个表格)
        List<RobotDataReportExport> robotDataReportExportList = new ArrayList<>();
        //分页查询（每页10条）
        int page = 1;
        robotDataReportQuery.setCurrent(page); //只查第一页
        robotDataReportQuery.setSize(10); //每页查询10个
        Page<RobotDataReportVo> robotDataReportVoPage = robotDataReport(robotDataReportQuery);
        while (robotDataReportVoPage != null && robotDataReportVoPage.getRecords() != null && robotDataReportVoPage.getRecords().size() > 0) {
            for (RobotDataReportVo robotDataReportVo : robotDataReportVoPage.getRecords()) {
                RobotDataReportExport robotDataReportExport = new RobotDataReportExport();
                BeanUtils.copyProperties(robotDataReportVo, robotDataReportExport);
                robotDataReportExportList.add(robotDataReportExport);

                //判断条数，如果条数大于10000条，生成excel文件
                if(robotDataReportExportList.size() >= exportExcelMaxNum){
                    ByteArrayOutputStream byteArrayOutputStream = null;
                    try {
                        //导出的文件序号,每次导出+1
                        exportFileNumber ++ ;
                        String fileName = "机器人数据报表_" + exportFileNumber +".xlsx";
                        //创建流
                        byteArrayOutputStream = new ByteArrayOutputStream();
                        //打包成ZIP文件
                        EasyExcel.write(byteArrayOutputStream, RobotDataReportExport.class).registerConverter(new LongStringConverter()).sheet("机器人数据报表").doWrite(robotDataReportExportList);
                        ZipUtils.zip(out, new ByteArrayInputStream(byteArrayOutputStream.toByteArray()), fileName);
                        byteArrayOutputStream.close();
                        //清空本次导出的数据列表
                        robotDataReportExportList.clear();
                    }catch (Exception e){
                        if(byteArrayOutputStream != null){
                            try {
                                byteArrayOutputStream.close();
                            } catch (IOException ex) {
                                logger.error(ex.getMessage(), ex);
                            }
                        }
                        logger.error("----导出机器人数据报表异常--error={}", e.getMessage());
                    }
                }

            }
            //循环查询下一页
            page ++;
            //最多支持导出100页数据
            if(page > 100){
                break;
            }
            robotDataReportQuery.setCurrent(page);
            robotDataReportVoPage = robotDataReport(robotDataReportQuery);
        }

        //最后将剩余不足10000条的记录，生成excel文件
        if(robotDataReportExportList.size() > 0){
            ByteArrayOutputStream byteArrayOutputStream = null;
            try {
                //导出的文件序号,每次导出+1
                exportFileNumber ++ ;
                String fileName = "机器人数据报表_" + exportFileNumber +".xlsx";
                //创建流
                byteArrayOutputStream = new ByteArrayOutputStream();
                //打包成ZIP文件
                EasyExcel.write(byteArrayOutputStream, RobotDataReportExport.class).registerConverter(new LongStringConverter()).sheet("机器人数据报表").doWrite(robotDataReportExportList);
                ZipUtils.zip(out, new ByteArrayInputStream(byteArrayOutputStream.toByteArray()), fileName);
                byteArrayOutputStream.close();
                //清空本次导出的数据列表
                robotDataReportExportList.clear();
            }catch (Exception e){
                if(byteArrayOutputStream != null){
                    try {
                        byteArrayOutputStream.close();
                    } catch (IOException ex) {
                        logger.error(ex.getMessage(), ex);
                    }
                }
                logger.error("----导出机器人数据报表异常--error={}", e.getMessage());
            }
        }

        try {
            // 注意关闭流的顺序，在上传oss之前必须关闭流否则下载解压的时候会报“文件末端错误”的问题
            outputStream.close();
            out.close();
        }catch (Exception e){
            logger.error("----导出机器人数据报表异常关闭流异常--error={}", e.getMessage());
        }finally {

        }

        //上传文件到OSS当中
        InputStream byteArrayInputStream = new ByteArrayInputStream(outputStream.toByteArray());
        String zipFileName = "机器人数据报表_" + System.currentTimeMillis() + ".zip";
        //上传文件通讯录
        exportInfoService.uploadExportFile(byteArrayInputStream, robotDataReportExportResultDto.getMerId(), zipFileName, exportAmountVo, ExportInfoTypeEnum.EXPORT_INFO_ROBOT_DATA_REPORT.getId());

        //往reids插入本次下载，允许30分钟下载一次，避免频繁提交
        redisTemplate.opsForValue().set(String.format(CacheKey.ROBOT_DATA_REPORT_EXPORT, robotDataReportExportResultDto.getMerId()),robotDataReportExportResultDto.getMerId()+"",30, TimeUnit.MINUTES);

    }

}
